<?php


namespace common\service;


use common\exception\LogicException;
use common\model\EntityModel;
use common\model\TaskModel;
use common\model\TaskRelationModel;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;

class DismantleTaskService
{

    use SingletonTrait;

    /**
     * 子任务转换成父任务
     * @param $task
     * @return array|false|mixed|string|null
     */
    public function dismantleTaskTransformation($task)
    {
        if (empty($task)) {
            return [];
        }
        $taskJson = json_decode($task['json'], true);
        if (!empty($taskJson['is_dismantle_task']) && $taskJson['is_dismantle_task'] == 'true') {
            $taskRelation = model(TaskRelationModel::class)
                ->setSuffix(sprintf('_project_%d', $task['project_id']))
                ->alias('task_relation')
                ->where(['relation_type' => 'dismantle_task', 'target_task_id' => $task['id']])
                ->find();
            return model(TaskModel::class)->where(['id' => $taskRelation['source_task_id']])->find();
        }
        return $task;
    }

    /**
     * 删除子任务
     * @param $id
     * @return false|float|int|mixed|string|void
     */
    public function deleteDismantle($id)
    {
        $taskData = model(TaskModel::class)->where(['id' => $id, 'is_assignee' => 'no'])->find();
        if (!empty($taskData)) {
            $taskJson = json_decode($taskData['json'], true);
            if (!empty($taskJson['is_dismantle_task'])) {
                return model(TaskModel::class)->where(['id' => $id])->delete();
            }
        }
    }

    /**
     * 获取子任务的父任务
     * @param $taskIds
     * @return array|mixed|string
     */
    public function getDismantleParentTaskIds($taskIds)
    {
        if (empty($taskIds)) {
            return [];
        }
        $list = model(TaskRelationModel::class)->alias('tr')->field('*')->join("task on task.id =  tr.source_task_id")
            ->where(['relation_type' => 'dismantle_task', 'target_task_id' => ['IN', $taskIds]])
            ->select();
        if (empty($list)) {
            return [];
        }
        return $list;
    }

    /**
     * 获取主任务下的所有子任务id
     * @param $taskIds
     * @param string $relationType
     * @return array
     */
    public function getDismantleTaskIds($taskIds, $relationType = TaskRelationModel::RELATION_TYPE_DISMANTLE_TASK)
    {
        if (empty($taskIds)) {
            return [];
        }
        $taskList = model(TaskModel::class)->where(['id' => ['IN', $taskIds]])->field('id,project_id')->select();
        if (empty($taskList)) {
            return [];
        }
        $projectId = $taskList[0]['project_id'] ?? 0;
        $list = model(TaskRelationModel::class)
            ->setSuffix(sprintf('_project_%d', $projectId))
            ->alias('task_relation')
            ->field('target_task_id as id,source_task_id')
            ->where(['relation_type' => $relationType, 'source_task_id' => ['IN', $taskIds]])
            ->select();
        if (empty($list)) {
            return [];
        }
        return $list;
    }

    /**
     * 检查子任务数据
     * @param $data
     * @return string
     */
    public function dismantleCheckTask($data)
    {
        // 校验子任务不可再分
        $isRelation = model(TaskRelationModel::class)
            ->setSuffix(sprintf('_project_%d', $data['project_id']))
            ->alias('task_relation')
            ->field('id')
            ->where(['relation_type' => 'dismantle_task', 'target_task_id' => $data['task_id']])
            ->find();
        if ($isRelation) {
            throw new LogicException('dismantle task inseparable', ErrorCode::TASK_NOT_EXIST);
        }
        // 校验是否和主任务名字冲突
        $entityData = model(EntityModel::class)
            ->field('entity.name')
            ->join('task on task.entity_id = entity.id')
            ->where(['task.id' => $data['task_id'], 'entity.name' => $data['dismantle_name']])
            ->find();
        if (!empty($entityData)) {
            throw new LogicException('The task name already exists', ErrorCode::DISMANTLE_IS_EXISTS);
        }
        // 校验是否和产生过子任务的名字有冲突
        $taskRelationList = model(TaskRelationModel::class)
            ->setSuffix(sprintf('_project_%d', $data['project_id']))
            ->alias('task_relation')
            ->field('task.name,task.json')
            ->join("task on task_relation.target_task_id = task.id")
            ->where(['task_relation.relation_type' => 'dismantle_task', 'task_relation.source_task_id' => $data['task_id']])
            ->select();

        $needDismantleName = [];
        foreach ($taskRelationList as $value) {
            $jsonArr = json_decode($value['json'], true);
            if (empty($jsonArr['dismantle_name'])) {
                continue;
            }
            $needDismantleName[] = $jsonArr['dismantle_name'];
        }
        if (in_array($data['dismantle_name'], $needDismantleName)) {
            throw new LogicException('The task name already exists', ErrorCode::DISMANTLE_IS_EXISTS);
        }
        return '';
    }

    /**
     *  拆分任务
     * @param $data
     * @return bool|float|int|string
     * @throws Exception
     * @throws \Exception
     * @throws \Throwable|\Throwable|\Throwable
     */
    public function dismantleSetStepTask($data)
    {
        $this->dismantleCheckTask($data);
        // 查询当前任务信息
        $taskModel = model(TaskModel::class);
        $taskData = $taskModel->field('*')->where(['id' => $data['task_id']])->find();

        if (!$taskData) {
            throw new LogicException('task no exist', ErrorCode::TASK_NOT_EXIST);
        }
        $taskGenerateService = TaskGenerateService::getInstance();
        // 组织子任务数据
        $dismantleTaskData = $taskGenerateService->getDismantleStepCategoryTaskData($taskData, $data);
        // 保存子任务
        $taskModel->startTrans();
        try {
            $requestDismantleTask = model(TaskModel::class)->add($dismantleTaskData);
            if (!$requestDismantleTask) {
                throw new LogicException('dismantle task add fail', ErrorCode::DISMANTLE_TASK_CREATE_FAIL);
            }
            $taskRelationData = [
                'source_task_id' => $data['task_id'],
                'target_task_id' => $requestDismantleTask,
                'relation_type' => 'dismantle_task'
            ];
            // 绑定关联关系
            $requestRelation = model(TaskRelationModel::class)
                ->setSuffix(sprintf('_project_%d', $data['project_id']))
                ->addItem($taskRelationData);
            if (!$requestRelation) {
                throw new LogicException('bind dismantle task fail', ErrorCode::BIND_DISMANTLE_RELATION_TASK_FAIL);
            }
            $taskModel->commit();
            return $requestDismantleTask;
        } catch (\Throwable $e) {
            $taskModel->rollback();
            throw $e;
        }
    }

    /**
     * 子任务转换成父任务
     * @param $tasks
     * @return array|mixed
     */
    public function batchDismantleTaskTransformationMap($tasks)
    {
        if (empty($tasks)) {
            return [];
        }

        $dismantleTaskIds = [];
        foreach ($tasks as $taskItem) {
            $taskJson = json_decode($taskItem['json'], true);
            if (!empty($taskJson['is_dismantle_task']) && $taskJson['is_dismantle_task'] == 'true') {
                $dismantleTaskIds[] = $taskItem['id'];
            }
        }

        if (empty($dismantleTaskIds)) {
            return [];
        }
        $projectData = model(TaskModel::class)->where(['id' => ['IN', $dismantleTaskIds]])->field('project_id')->find();
        $projectId = $projectData['project_id'];
        $taskRelationList = model(TaskRelationModel::class)
            ->setSuffix(sprintf('_project_%d', $projectId))
            ->alias('task_relation')
            ->where(['relation_type' => 'dismantle_task', 'target_task_id' => ["IN", $dismantleTaskIds]])
            ->select();
        $targetTaskMap = array_column($taskRelationList, null, 'target_task_id');
        $sourceTaskId = array_unique(array_column($taskRelationList, 'source_task_id'));
        $sourceTaskList = model(TaskModel::class)->where(['id' => ["IN", $sourceTaskId]])->select();
        $sourceTaskList = array_column($sourceTaskList, null, 'id');

        foreach ($targetTaskMap as $targetTaskIndex => $targetTaskItem) {
            if (isset($sourceTaskList[$targetTaskItem['source_task_id']])) {
                $targetTaskMap[$targetTaskIndex] = $sourceTaskList[$targetTaskItem['source_task_id']];
            } else {
                unset($targetTaskMap[$targetTaskIndex]);
            }
        }

        return $tasks;
    }

    /**
     * 子任务转换成父任务
     * @param $taskList
     * @return array|false|mixed|string|null
     */
    public function dismantleTaskTransformationBatch($taskList)
    {
        if (empty($taskList)) {
            return [];
        }
        $targetTaskIdList = [];
        $disMap = [];
        foreach ($taskList as $taskIndex => $task) {
            $taskJson = json_decode($task['json'], true);
            if (!empty($taskJson['is_dismantle_task']) && $taskJson['is_dismantle_task'] == 'true') {
                $targetTaskIdList[] = $task['id'];
                $disMap[$task['id']] = &$taskList[$taskIndex];
            }
        }
        if (!empty($targetTaskIdList)) {
            $taskRelationTaskList = model(TaskRelationModel::class)
                ->setSuffix(sprintf('_project_%d', $targetTaskIdList))
                ->alias('tr')
                ->join('task on task.id = tr.source_task_id')
                ->where(['tr.relation_type' => 'dismantle_task', 'tr.target_task_id' => ['IN', $targetTaskIdList]])
                ->field('tr.target_task_id,task.*')
                ->select();
            foreach ($taskRelationTaskList as $taskRelationTaskItem) {
                $disMap[$taskRelationTaskItem['target_task_id']] = $taskRelationTaskItem;
            }
        }
        return $taskList;
    }
}
